Skip to content

usdsui single asset loop#59

Merged
harshaalphafi merged 6 commits intomainfrom
feature/slush-usdsui
Apr 15, 2026
Merged

usdsui single asset loop#59
harshaalphafi merged 6 commits intomainfrom
feature/slush-usdsui

Conversation

@Zorag44
Copy link
Copy Markdown
Contributor

@Zorag44 Zorag44 commented Apr 11, 2026

No description provided.

@Zorag44 Zorag44 marked this pull request as ready for review April 13, 2026 18:56
@Zorag44 Zorag44 requested a review from jangid as a code owner April 13, 2026 18:57
@Zorag44 Zorag44 requested a review from rg-alpha April 13, 2026 18:57
@rg-alpha rg-alpha requested a review from 11felix April 13, 2026 20:44
Copy link
Copy Markdown
Contributor

@jangid jangid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

+188 / -11 across 3 files — adds USDSUI single-asset looping support with reward collection and multi-hop swapping via Bluefin DEX.


Issues

1. Swap direction likely inverted for USDC → USDSUI (critical)

In collectAndSwapRewards(), the final swap step for USDSUI pools has:

typeArguments: [this.poolLabel.asset.type, this.poolLabel.asset.type, usdcCoin.coinType],

This puts USDSUI as both the pool asset type AND the "from" coin, with USDC as the "to" coin. But the intent is to swap USDC → USDSUI. The getPoolIdBySymbolsAndProtocol call correctly uses ('USDC', 'USDSUI', 'bluefin'), but the type arguments and tx.pure.bool(false) for a_to_b look contradictory. Please verify against the Move contract's expected type param order — a wrong swap direction would lose user funds.

2. Hardcoded slippage tolerances with no documentation

Multiple magic numbers: 1000, 10, 10000. No comments explaining:

  • What unit they're in (basis points? DEX-specific?)
  • Why ALPHA→stSUI uses 1000, stSUI→SUI uses 10, and everything else uses 10000
  • If 10000 = 100% slippage, that's significant MEV risk

3. Reward coin list is hardcoded and not pool-aware

collectAndSwapRewards() fetches 10 specific coin types regardless of which rewards the pool actually earns. This means unnecessary RPC calls, manual updates when new reward tokens are added, and silent skipping of unknown reward types.

4. No error handling for missing Bluefin pools

getPoolIdBySymbolsAndProtocol / getPoolIdByTypesAndProtocol are awaited inside a loop with no handling if a Bluefin pool doesn't exist for a reward pair. This would throw and abort the entire deposit/withdraw transaction.

5. let should be const

let coinTypes = [...] is never reassigned — should be const.

6. Test file left in dry-run mode

testRun.ts has executeTransactionBlock commented out. Fine for testing, but worth calling out so it doesn't surprise anyone.

7. Empty PR description

No context on what USDSUI single-asset looping is, why reward collection happens during deposit/withdraw, or how to test.


Verdict

The core logic follows the existing SingleAssetLooping pattern and looks structurally sound. However, the USDC→USDSUI swap type arguments need verification against the Move contract before merging. The slippage values also need documentation or a confirming comment that 10000 is intentional and safe.

@Zorag44
Copy link
Copy Markdown
Contributor Author

Zorag44 commented Apr 14, 2026

Review

+188 / -11 across 3 files — adds USDSUI single-asset looping support with reward collection and multi-hop swapping via Bluefin DEX.

Issues

1. Swap direction likely inverted for USDC → USDSUI (critical)

In collectAndSwapRewards(), the final swap step for USDSUI pools has:

typeArguments: [this.poolLabel.asset.type, this.poolLabel.asset.type, usdcCoin.coinType],

This puts USDSUI as both the pool asset type AND the "from" coin, with USDC as the "to" coin. But the intent is to swap USDC → USDSUI. The getPoolIdBySymbolsAndProtocol call correctly uses ('USDC', 'USDSUI', 'bluefin'), but the type arguments and tx.pure.bool(false) for a_to_b look contradictory. Please verify against the Move contract's expected type param order — a wrong swap direction would lose user funds.

2. Hardcoded slippage tolerances with no documentation

Multiple magic numbers: 1000, 10, 10000. No comments explaining:

  • What unit they're in (basis points? DEX-specific?)
  • Why ALPHA→stSUI uses 1000, stSUI→SUI uses 10, and everything else uses 10000
  • If 10000 = 100% slippage, that's significant MEV risk

3. Reward coin list is hardcoded and not pool-aware

collectAndSwapRewards() fetches 10 specific coin types regardless of which rewards the pool actually earns. This means unnecessary RPC calls, manual updates when new reward tokens are added, and silent skipping of unknown reward types.

4. No error handling for missing Bluefin pools

getPoolIdBySymbolsAndProtocol / getPoolIdByTypesAndProtocol are awaited inside a loop with no handling if a Bluefin pool doesn't exist for a reward pair. This would throw and abort the entire deposit/withdraw transaction.

5. let should be const

let coinTypes = [...] is never reassigned — should be const.

6. Test file left in dry-run mode

testRun.ts has executeTransactionBlock commented out. Fine for testing, but worth calling out so it doesn't surprise anyone.

7. Empty PR description

No context on what USDSUI single-asset looping is, why reward collection happens during deposit/withdraw, or how to test.

Verdict

The core logic follows the existing SingleAssetLooping pattern and looks structurally sound. However, the USDC→USDSUI swap type arguments need verification against the Move contract before merging. The slippage values also need documentation or a confirming comment that 10000 is intentional and safe.

  • that number is not slippage. its minimum swap amount.
  • params are usdsui and usdc but a2b is false so swap should happen from usdc to usdsui
  • changed let to const

@11felix
Copy link
Copy Markdown
Contributor

11felix commented Apr 14, 2026

Since you changed poolLabel in alphafi-sdk-rust, you need to update it in parsePoolLabelEntry function in src/models/strategyContext.ts file as well

@Zorag44
Copy link
Copy Markdown
Contributor Author

Zorag44 commented Apr 14, 2026

Since you changed poolLabel in alphafi-sdk-rust, you need to update it in parsePoolLabelEntry function in src/models/strategyContext.ts file as well

poolLabel hasnt been changed.

Copy link
Copy Markdown
Contributor

@jangid jangid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed after Shrome's changes and clarifications.

Critical concern from prior review resolved by explanation:

  • The 10000 / 1000 / 10 values are minimum-swap-amount, not slippage bps — no MEV risk as I'd framed it.
  • For the USDC→USDSUI hop, type args [USDSUI, USDSUI, USDC] with a_to_b: false correctly swaps USDC→USDSUI per the Move signature [pool_asset, A, B].
  • letconst done.
  • collectAndSwapRewards now also called from claimWithdraw and cancelWithdraw — good catch.

Remaining nice-to-haves (non-blocking, follow-up welcome):

  • Add a short comment documenting that the u64 arg is min-swap-amount (and the unit), so the next reader doesn't repeat my misread.
  • Pool-aware reward list and graceful handling of missing Bluefin pools can be revisited later.

LGTM.

@harshaalphafi harshaalphafi merged commit cec6b64 into main Apr 15, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants